---------------------------------------------------
-- VC-OP: output port virtual channel
-- Revisions:
-- 13.06.07: IPIDX type was changed to binary from one-hot, 8-invalid value.
-- 16.02.09: Have added a AND gate between BT mux and OR. When IP_IDX swithes and there is a BT reuest for another VC,
--           there could be a glitch that sets incorrectly ri_sig. Now the bt_req is blocked when the the IP_IDX is not 
--           yet latched (additional condition of l_ip being low for passing over bt_req).

library ieee;
 use ieee.std_logic_1164.all;
 use ieee.std_logic_unsigned.all;
 use IEEE.std_logic_arith.all;

-- synopsys translate_off
-- synthesis translate_off
--library csx_HRDLIB_FTSM;
-- use csx_HRDLIB_FTSM.VCOMPONENTS.all;
-- synthesis translate_on
-- synopsys translate_on

library work;
 use work.router_pack.all;


-------------------------------------------------------------------------------
entity msl_ssl_op_top is
-------------------------------------------------------------------------------
port( 
      -- General Control: --
      RESET    : in  std_logic;  -- Active  

      -- Internal input i/f: --
      H_ARR    : in  signaling_ssl_bus_type;  -- #VCs (input) x #ports 
      BT_ARR   : in  signaling_ssl_bus_type;  -- #VCs (input) x #ports
      DATA_I   : in  data_ssl_op_bus_type;    -- #ports x #VCs (input)
      AI_ARR   : out signaling_ssl_bus_type;  -- #VCs (input) x #ports

      -- VCAC interface: --
      IPIDX    : in  vc_op_idx_type; --signaling_ssl_bus_type;  -- #VCs x #ports
      H        : out std_logic;               -- gate to VCAC
      BUSY     : out std_logic;

      -- External output i/f: --
      RO       : out std_logic;
      AO       : in  std_logic;
      DO       : out std_logic_vector(flit_width_con-1 downto 0)   
);           
-------------------------------------------------------------------------------
end msl_ssl_op_top ;
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
architecture msl_ssl_op_top_arch of msl_ssl_op_top is
-------------------------------------------------------------------------------

component latch_ctrl3 
port( 
      -- General Control: --
      RESET  : in  std_logic;  -- Active  

      -- External input i/f: --
      RI     : in  std_logic;
      AI     : out std_logic;

      -- Latch control i/f: --
      LDO    : out std_logic;
      DI     : in  std_logic;

      -- Internal output i/f: --
      RO     : out std_logic;
      AO     : in  std_logic
); 
end component;

component delay_line
generic(
   num_of_buffers : integer := 1
);
port( 
      DI  : in   std_logic;   
      DO  : out  std_logic   
);           
end component;

component lachq1  -- latch with clear (act. low) and enable (active high).
port(
      E                              :	in    std_logic;
      D                              :	in    std_logic;
      CDN                            :	in    std_logic;
      Q                              :	out   std_logic
);
end component;

component labhb1 -- setn, resetn, enable
port(
      E                              :	in    std_logic;
      D                              :	in    std_logic;
      CDN                            :	in    std_logic;
      SDN                            :	in    std_logic;
      Q                              :	out   std_logic;
      QN                             :	out   std_logic
);
end component;

component lanlq1 -- data latch with enable active low and single output.
port(
      EN                             :	in    std_logic;
      D                              :	in    std_logic;
      Q                              :	out   std_logic
);
end component;

component c_element
port( 
      -- Input i/f: --
      A     : in  std_logic;
      B     : in  std_logic;

      -- output i/f: --
      Q     : out std_logic
);           
end component;

signal bt_req   : std_logic;

signal l_ip_not, l_ip : std_logic;
--signal ip_idx   : signaling_ssl_bus_type;
signal ip_idx   : std_logic_vector(3 downto 0);
--signal ip_idx_arr : std_logic_vector(num_of_vc_con*num_of_ports_con-1 downto 0);

signal g_out : std_logic;
signal ri_sig, ai_sig : std_logic;

signal hand_ind : std_logic;
signal data_out_int   : std_logic_vector(flit_width_con-1 downto 0);
signal data_bef_latch : std_logic_vector(flit_width_con-1 downto 0);

signal ldo, di : std_logic;

signal sig_high : std_logic;

signal reset_not         : std_logic;
signal ldo_not           : std_logic;

signal ipidx_bin : std_logic_vector(3 downto 0); --IPIDX 

signal tail_and_no_hs : std_logic;

signal g_out_del, g_out_glitch_filtered : std_logic;

begin

sig_high <= '1';
DO <= data_out_int;
reset_not <= not RESET;
H <= g_out_glitch_filtered; --g_out; -- gate to VCAC -- 27.12.07


-- A. IP Index Latch and Acknoweledge out: --
l_ip_not <= not l_ip;

ipidx_bin <= conv_std_logic_vector(IPIDX, 4);
                             
vc_op_idx_gen: for j in 0 to 3 generate -- 4 bits -- log2( (num_of_vc_con-1)*(num_of_ports_con-1)+1 )

  u_ip_idx_latch: lachq1
  port map(
      E                              => l_ip,
      D                              => ipidx_bin(j),
      CDN                            => reset_not,
      Q                              => ip_idx(j)
  );
  
end generate; -- j loop
 
ai_arr_proc: process(ai_sig, ip_idx)
begin
 AI_ARR <= (others=>(others=>'0')); -- #VCs (input) x #ports

 case ip_idx is --ip_idx_arr is
  when "0000" =>
   AI_ARR(0)(0) <= ai_sig;
  when "0001" =>
   AI_ARR(0)(1) <= ai_sig;
  when "0010" =>
   AI_ARR(0)(2) <= ai_sig;
  when "0011" =>
   AI_ARR(0)(3) <= ai_sig;
  when "0100" =>
   AI_ARR(1)(0) <= ai_sig;
  when "0101" =>
   AI_ARR(1)(1) <= ai_sig;
  when "0110" =>
   AI_ARR(1)(2) <= ai_sig;
  when "0111" =>
   AI_ARR(1)(3) <= ai_sig;
  when others =>
   AI_ARR <= (others=>(others=>'0')); -- #VCs (input) x #ports
 end case;

end process;

 
--msl_op_ivc_gen: for i in 0 to (num_of_vc_con-1) generate
-- msl_op_ip_gen: for j in 0 to (num_of_ports_con-1) generate
--
--  u_ip_idx_latch: lachq1
--  port map(
--      E                              => l_ip,
--      D                              => IPIDX(i)(j),
--      CDN                            => reset_not,
--      Q                              => ip_idx(i)(j)
--  );
--
-- AI_ARR(i)(j) <= ai_sig and (ip_idx(i)(j)) ; 
--
-- end generate; -- j (ip ports)
--end generate;  -- i (input vc)

-- B. Grants Mux: --
--ip_idx_arr <= ip_idx(1) & ip_idx(0);

grant_in_mux_proc: process(H_ARR, ip_idx) --ip_idx_arr)
begin
 case ip_idx is --ip_idx_arr is
  when "0000" =>
   g_out <= H_ARR(0)(0);
  when "0001" =>
   g_out <= H_ARR(0)(1);
  when "0010" =>
   g_out <= H_ARR(0)(2);
  when "0011" =>
   g_out <= H_ARR(0)(3);
  when "0100" =>
   g_out <= H_ARR(1)(0);
  when "0101" =>
   g_out <= H_ARR(1)(1);
  when "0110" =>
   g_out <= H_ARR(1)(2);
  when "0111" =>
   g_out <= H_ARR(1)(3);   
  when others =>
   g_out <= '0';
 end case;
end process;

-- C. BT-OR: --
-- BT-Requests are also MUXed since in multi-VC system there can be more than one BT request
-- concurrently
bt_in_mux_proc: process(BT_ARR, ip_idx) --ip_idx_arr)
begin
 case ip_idx is --ip_idx_arr is
  when "0000" =>
   bt_req <= BT_ARR(0)(0);
  when "0001" =>
   bt_req <= BT_ARR(0)(1);
  when "0010" =>
   bt_req <= BT_ARR(0)(2);
  when "0011" =>
   bt_req <= BT_ARR(0)(3);
  when "0100" =>
   bt_req <= BT_ARR(1)(0);
  when "0101" =>
   bt_req <= BT_ARR(1)(1);
  when "0110" =>
   bt_req <= BT_ARR(1)(2);
  when "0111" =>
   bt_req <= BT_ARR(1)(3);   
  when others =>
   bt_req <= '0';
 end case;
end process;

-- HAVE TO PUT A GLITCH FILTER ON G_OUT. Can glitch due to ip_idx switching! the glitch filter filters the intermidiate stage of the g_out suring the ip_idx switching. 27.12.07
u_delay_line: delay_line
generic map(
   num_of_buffers => 1
)
port map( 
      DI  => g_out,  
      DO  => g_out_del  
);

g_out_glitch_filtered <= g_out and g_out_del;


-- D. Request to Latch Controller and input to C-element: --
ri_sig   <= g_out_glitch_filtered or (bt_req and l_ip_not);   -- request input to the controller 27.12.07; 16.02.09: bt_req depends on L_IP being low (IP_IDX being latched and stable)
hand_ind <= ai_sig nor ri_sig; -- signal to c-element

-- E.  C-element: --
-- Bug fix: 15.12.07: If the external interface is stuck, then the internal interface 
--  can still run, and it could then change the value of the ip_idx, which is open after
--  the last tail (the tail is still is on since the external i/f (ack) is not released yet).
tail_and_no_hs <= data_out_int(flit_width_con-1) and (not ai_sig);

-- E.  C-element: --
u_c_element: c_element
port map( 
      A     => hand_ind,
      B     => tail_and_no_hs,

      Q     => l_ip
); 


-- F.  Latch-Ctrl: --
u_latch_ctrl3: latch_ctrl3 
port map( 
      RESET  => RESET,    

      RI     => ri_sig,
      AI     => ai_sig,

      LDO    => ldo,
      DI     => di,

      RO     => RO,
      AO     => AO
); 


-- G. DATA mux: --
data_in_mux_proc: process(DATA_I, ip_idx) --ip_idx_arr)
begin
 case ip_idx is --ip_idx_arr is
  when "0000" =>
   data_bef_latch <= DATA_I(0)(0); -- VC0, port0
  when "0001" =>
   data_bef_latch <= DATA_I(1)(0);
  when "0010" =>
   data_bef_latch <= DATA_I(2)(0);
  when "0011" =>
   data_bef_latch <= DATA_I(3)(0);
  when "0100" =>
   data_bef_latch <= DATA_I(0)(1);
  when "0101" =>
   data_bef_latch <= DATA_I(1)(1);
  when "0110" =>
   data_bef_latch <= DATA_I(2)(1);
  when "0111" =>
   data_bef_latch <= DATA_I(3)(1); -- VC1, port3
  when others =>
   data_bef_latch <= DATA_I(0)(0);
 end case;
end process;

-- H: Busy generation:
--BUSY <= ip_idx(0)(0) or ip_idx(0)(1) or ip_idx(0)(2) or ip_idx(0)(3) or
--        ip_idx(1)(0) or ip_idx(1)(1) or ip_idx(1)(2) or ip_idx(1)(3);
BUSY <= l_ip_not;

-- I. Data Latch : --
-- Tail Latch should be reset at the beginning of the operation
 ldo_not <= not ldo;
 
 tail_data_latch: labhb1
 port map(
      D                              => data_bef_latch(flit_width_con-1),
      E                              => ldo_not, --ldo -- when high then the latch is transparent
      Q                              => data_out_int(flit_width_con-1),
      QN                             => open,
      CDN                            => sig_high,
      SDN                            => reset_not   -- resetting to high (TAIL)
 );



data_latch_gen: for i in 0 to (flit_width_con-2) generate
  
 data_latch: lanlq1
 port map(
      D     => data_bef_latch(i),
      EN    => ldo, -- -- when low then the latch is transparent
      Q     => data_out_int(i)
 );

end generate;

-------------------------------------------------------------------------------
end msl_ssl_op_top_arch;
-------------------------------------------------------------------------------                 

   
-------------------------------------------------------------------------------
configuration  msl_ssl_op_top_cfg  of msl_ssl_op_top is
-------------------------------------------------------------------------------
   for msl_ssl_op_top_arch
   end for;
-------------------------------------------------------------------------------
end  msl_ssl_op_top_cfg;              
-------------------------------------------------------------------------------
                 
